
#include "Timer.hpp"
#include <sys/timerfd.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <iostream>

using namespace std;

namespace zhb
{
    bool Timer::settimer(size_t interval)
    { // s ms  在此我们用ms  1200
        bool ret = true;
        struct itimerspec new_value = {0};
        new_value.it_interval.tv_sec = (interval / 1000);                // ms--->s   1s
        new_value.it_interval.tv_nsec = (interval % 1000) * 1000 * 1000; // 200 ms---> 200 000 000 nm
        new_value.it_value = new_value.it_interval;                      // 在此刻过上1200ms才触发
        if (timerfd_settime(m_timerId, 0, &new_value, nullptr) < 0)
        { // 定时器设置错误
            ret = false;
        }
        return ret;
    }

    Timer::Timer() : m_timerId(-1), m_callback(nullptr) {}
    Timer::~Timer() { close_timer(); }

    bool Timer::init()
    {
        bool ret = true;
        if (m_timerId > 0)
        {
            return ret;
        }
        m_timerId = ::timerfd_create(CLOCK_MONOTONIC, 0);
        if (m_timerId < 0)
        {
            ret = false;
        }
        return ret;
    }
    bool Timer::set_timer(const TimerCallback &cb, size_t interval)
    {
        bool ret = false;
        if (m_timerId > 0 && settimer(interval))
        {
            m_callback = cb;
            ret = true;
        }
        return ret;
    }
    bool Timer::resete_timer(size_t interval)
    {
        bool ret = false;
        if (m_timerId > 0 && m_callback != nullptr && settimer(interval))
        {
            ret = true;
        }
        return ret;
    }

    void Timer::handle_event()
    {
        uint64_t exp_cnt=0;
        if(read(m_timerId,&exp_cnt,sizeof(exp_cnt))!=sizeof(exp_cnt)) return;    //若缓冲区有数据则不清理会一直触发，且时间久了缓冲区会爆
        if (m_callback != nullptr){m_callback();}
    }
    size_t Timer::get_TimerId() const { return m_timerId; }
    bool Timer::close_timer()
    {
        bool ret = false;
        if (m_timerId > 0)
        {
            close(m_timerId);
            m_timerId = -1;
            m_callback = nullptr;
            ret = true;
        }
        return ret;
    }
}